
import std.stdio;
import core.thread;
import std.functional;
public import std.traits;
import std.typecons;
import std.typetuple;

class AA
{
    void show(int i)
    {
        writeln("i = ", i); // the value is not(0,1,2,3), it all is 2.
    }
    
    void show(int i, int b)
    {
        b += i * 10;
        writeln("b = ", b); // the value is not(0,1,2,3), it all is 2.
    }
    
    void aa()
    {
         writeln("aaaaaaaa "); 
    }
    
    void dshow(int i, string str, double t)
    {
        writeln("i = ", i, "   str = ", str, "   t = ",t);
    }
}


void listRun(int i)
{
     writeln("i = ", i); 
}

void listRun2(int i,int b)
{
     writeln("i = ", i, "  b = ", b); 
}

void list()
{
    writeln("bbbbbbbbbbbb");
}

void dooo(Thread[] t1, Thread[] t2, AA a)
{
    foreach (i ; 0..4) {
        auto th = new Thread(bind!(void delegate(int,int))(&a.show,i,i));
        t1[i]= th;
        auto th2 = new Thread(bind(&listRun,(i + 10)));
        t2[i]= th2;
    }
}

void main() {
    auto tdel = bind(&listRun);
    tdel(9);
    bind(&listRun2,4)(5);
    bind(&listRun2,40,50)();
    
    AA a = new AA();
    bind(&a.dshow,5,"hahah")(20.05);
    
    Thread[4] _thread;
    Thread[4] _thread2;
    // AA a = new AA();
    
    dooo(_thread,_thread2,a);
    
    foreach(i;0..4)
    {
        _thread[i].start();
    }
    
    foreach(i;0..4)
    {
        _thread2[i].start();
    }
    
}


/*auto bind(T, Args...)(auto ref T fun,Args args) if (isCallable!(T))//if (isDelegate!T)
{
    static if(is(Args == void)) {
        static if(isDelegate!T)
            return fun;
        else
            return toDelegate(fun);
    } else{
	return delegate(){return fun(forward!args);};
    }
}*/

auto  bind(T,Args...)(auto ref T fun,Args args) if (isCallable!(T))
{
    alias FUNTYPE = Parameters!(fun);
    static if(is(Args == void)) {
        static if(isDelegate!T)
            return fun;
        else 
            return toDelegate(fun);
    } else static if(FUNTYPE.length > args.length){
        alias DTYPE = FUNTYPE[args.length..$];
        return 
            delegate(DTYPE ars){
                TypeTuple!(FUNTYPE) value;
                value[0..args.length] = args[];
                value[args.length..$] = ars[];
                return fun(value);
            };
    } else {
        return delegate(){return fun(args);};
    }
}
/*
pipi    MFUN(string[] list)
{
    pip = new pip();
    loop:
    obj.frr(list[i]);
    pip.add(obj);
    
    return pip;
}

bind(&MFUN,list[]);

addRouter(string path,void function(req,res) fun, Pipe delegate() brfore = null, Pipe delegate() back = null);
{
    addRouter(path,bind(fun), cdel)
}

addRouter(string path,void delegate(req,res) fun, Pipe delegate());

addRouter(path,bind(&fun,name),bind(&fun2,list));

string[] cone;

bind(&fun,name);
void delegate(req,res);

void fun(string str, req,res)
{
    obj = object.f(str);
    if(ibj is null) {
    res.code = 404;
    red.done();
    return;
    }
    SCOPE(EXIT) OBJ.DER();
    if((cast(T)obj).__calldun(req,res) == false)
    {
    }
    
}


class RouClis
{
    string pacth;
    delegateCall _call; // void delegate(req,res) 
    delegateD _broew;
    delegateD back;
}

AUTO FPIP = DBREOR();
FPIP.START();
auto pip = _broew();
pip.start(REQ,RES);
_CALL(REQ,RES);
PIP = BACK();
PIP.STAR(REQ,RES);


*/
